#include <vf_ShowSection3d.h>
#include <igl.h>

namespace VFAdapter {

CmdShowSection3D::CmdShowSection3D()
    : CEventSink<fw::ISEMouseEvents>(this),
      CEventSink<fw::ISELocateFilterEvents>(this),
      CEventSink<fw::ISEIGLDisplayEvents>(this),
      CEventSink<fw::ISECommandEvents>(this) {}

CmdShowSection3D::CmdShowSection3DPtr CmdShowSection3D::GetInstance() {
  static ATL::CComPtr<ATL::CComObject<CmdShowSection3D>> s_cmdManager = nullptr;
  ATL::CComObject<CmdShowSection3D> *cmdManager = nullptr;
  if (s_cmdManager == nullptr) {
    ATL::CComObject<CmdShowSection3D>::CreateInstance(&cmdManager);
    s_cmdManager = cmdManager;
  }
  return s_cmdManager;
}

void CmdShowSection3D::DisConnnectEvent() {
  // 解绑
  CEventSink<fw::ISECommandEvents>::DisConnect();
  CEventSink<fw::ISEMouseEvents>::DisConnect();
  CEventSink<fw::ISELocateFilterEvents>::DisConnect();
  CEventSink<fw::ISEIGLDisplayEvents>::DisConnect();
}

void CmdShowSection3D::StartCommand() {
  HRESULT hr;
  m_pSeCmd = SEAPP->CreateCommand(cs::seCmdFlag::seNoDeactivate);
  m_pSeMouse = m_pSeCmd->GetMouse();

  CEventSink<fw::ISECommandEvents>::Connect(m_pSeCmd);
  CEventSink<fw::ISEMouseEvents>::Connect(m_pSeMouse);
  CEventSink<fw::ISELocateFilterEvents>::Connect(m_pSeMouse);
  fw::WindowPtr pActiveWindow = SEAPP->GetActiveWindow();
  CEventSink<fw::ISEIGLDisplayEvents>::Connect(
      pActiveWindow->GetView()->GetGLDisplayEvents());
  m_pSeCmd->Start();
}
CmdShowSection3D::~CmdShowSection3D() {

  m_pSeMouse.Detach();
  m_pSeCmd.Detach();
  // m_pUiEvent = nullptr;
  // m_pMouseEvent = nullptr;
}

STDMETHODIMP_(HRESULT __stdcall) CmdShowSection3D::raw_Activate(void) {
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  HRESULT hr = S_OK;

  return hr;
}

STDMETHODIMP_(HRESULT __stdcall) CmdShowSection3D::raw_Deactivate(void) {
  DisConnnectEvent();
  return S_OK;
}

STDMETHODIMP_(HRESULT __stdcall) CmdShowSection3D::raw_Terminate(void) {
  return S_OK;
}

STDMETHODIMP_(HRESULT __stdcall)
CmdShowSection3D::raw_Idle(long lCount, VARIANT_BOOL *pbMore) { return S_OK; }

STDMETHODIMP_(HRESULT __stdcall)
CmdShowSection3D::raw_KeyDown(short *KeyCode, short Shift) { return S_OK; }

STDMETHODIMP_(HRESULT __stdcall)
CmdShowSection3D::raw_KeyPress(short *KeyAscii) { return S_OK; }

STDMETHODIMP_(HRESULT __stdcall)
CmdShowSection3D::raw_KeyUp(short *KeyCode, short Shift) { return S_OK; }

STDMETHODIMP_(HRESULT __stdcall)
CmdShowSection3D::raw_MouseMove(short sButton, short sShift, double dX,
                                double dY, double dZ,
                                LPDISPATCH pWindowDispatch, long lKeyPointType,
                                LPDISPATCH pGraphicDispatch) {
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  return S_OK;
}

STDMETHODIMP_(HRESULT __stdcall) CmdShowSection3D::raw_BeginDisplay(void) {

  return S_OK;
}

STDMETHODIMP_(HRESULT __stdcall) CmdShowSection3D::raw_EndDisplay(void) {
  return S_OK;
}

STDMETHODIMP_(HRESULT __stdcall)
CmdShowSection3D::raw_BeginIGLMainDisplay(LPUNKNOWN pUnk) {
  IGLPtr pGL = pUnk;
  if (nullptr == pGL || m_drawingList.empty())
    return S_FALSE;
  pGL->glColor3i(1, 1, 0);
  pGL->glLineWidth(2);

  for (auto const &drawingGeometry : m_drawingList) {
    pGL->glBegin(GL_LINE_STRIP);
    for (auto const &point : drawingGeometry) {
      pGL->glVertex3dv(point.data());
    }
    pGL->glEnd();
  }

  return S_OK;
}

STDMETHODIMP_(HRESULT __stdcall)
CmdShowSection3D::raw_EndIGLMainDisplay(LPUNKNOWN pGL) { return S_OK; }

STDMETHODIMP CmdShowSection3D::raw_MouseDown(short sButton, short sShift,
                                             double dX, double dY, double dZ,
                                             LPDISPATCH pWindowDispatch,
                                             long lKeyPointType,
                                             LPDISPATCH pGraphicDispatch) {
  return S_OK;
}

STDMETHODIMP CmdShowSection3D::raw_MouseUp(short sButton, short sShift,
                                           double dX, double dY, double dZ,
                                           LPDISPATCH pWindowDispatch,
                                           long lKeyPointType,
                                           LPDISPATCH pGraphicDispatch) {
  return S_OK;
}

STDMETHODIMP CmdShowSection3D::raw_MouseClick(short sButton, short sShift,
                                              double dX, double dY, double dZ,
                                              LPDISPATCH pWindowDispatch,
                                              long lKeyPointType,
                                              LPDISPATCH pGraphicDispatch

) {
  return S_OK;
}

STDMETHODIMP CmdShowSection3D::raw_MouseDblClick(
    short sButton, short sShift, double dX, double dY, double dZ,
    LPDISPATCH pWindowDispatch, long lKeyPointType, LPDISPATCH pGraphicDispatch

) {
  return S_OK;
}

STDMETHODIMP CmdShowSection3D::raw_MouseDrag(short sButton, short sShift,
                                             double dX, double dY, double dZ,
                                             LPDISPATCH pWindowDispatch,
                                             short DragState,
                                             long lKeyPointType,
                                             LPDISPATCH pGraphicDispatch) {
  return S_OK;
}

STDMETHODIMP CmdShowSection3D::raw_Filter(LPDISPATCH pGraphicDispatch,
                                          VARIANT_BOOL *vbValid) {
  return S_OK;
}

void CmdShowSection3D::ShowGeometry(
    std::vector<Eigen::Vector<double, 3>> &geometry) {
  m_drawingList.push_back(geometry);
}
} // namespace VFAdapter